Proper connect_port
[juce-lv2.git] / juce / source / extras / the jucer / src / ui / jucer_JucerDocumentHolder.cpp
blob7e44e08ad17ca16e0822b656252190a2c42a8904
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../jucer_Headers.h"
27 #include "jucer_JucerDocumentHolder.h"
28 #include "jucer_TestComponent.h"
29 #include "jucer_MainWindow.h"
30 #include "../model/jucer_ObjectTypes.h"
31 #include "jucer_ComponentLayoutPanel.h"
32 #include "jucer_PaintRoutinePanel.h"
33 #include "jucer_ResourceEditorPanel.h"
34 #include "../properties/jucer_ComponentTextProperty.h"
35 #include "../properties/jucer_ComponentChoiceProperty.h"
38 //==============================================================================
39 class ExtraMethodsList : public PropertyComponent,
40 public ListBoxModel,
41 public ChangeListener
43 public:
44 ExtraMethodsList (JucerDocument& doc)
45 : PropertyComponent ("extra callbacks", 250),
46 document (doc)
48 addAndMakeVisible (listBox = new ListBox (String::empty, this));
49 listBox->setRowHeight (22);
51 document.addChangeListener (this);
54 ~ExtraMethodsList()
56 document.removeChangeListener (this);
57 deleteAllChildren();
60 int getNumRows()
62 return methods.size();
65 void paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected)
67 if (row < 0 || row >= getNumRows())
68 return;
70 if (rowIsSelected)
71 g.fillAll (findColour (TextEditor::highlightColourId));
73 g.setColour (Colours::black);
74 g.setFont (height * 0.6f);
75 g.drawText (returnValues [row] + " " + baseClasses [row] + "::" + methods [row],
76 30, 0, width - 32, height,
77 Justification::centredLeft, true);
79 getLookAndFeel().drawTickBox (g, *this, 6, 2, 18, 18, document.isOptionalMethodEnabled (methods [row]), true, false, false);
82 void listBoxItemClicked (int row, const MouseEvent& e)
84 if (row < 0 || row >= getNumRows())
85 return;
87 if (e.x < 30)
88 document.setOptionalMethodEnabled (methods [row],
89 ! document.isOptionalMethodEnabled (methods [row]));
92 void paint (Graphics& g)
94 g.fillAll (Colours::white);
97 void resized()
99 listBox->setBounds (0, 0, getWidth(), getHeight());
102 void refresh()
104 baseClasses.clear();
105 returnValues.clear();
106 methods.clear();
107 initialContents.clear();
109 document.getOptionalMethods (baseClasses, returnValues, methods, initialContents);
111 listBox->updateContent();
112 listBox->repaint();
115 void changeListenerCallback (ChangeBroadcaster*)
117 refresh();
120 private:
121 JucerDocument& document;
122 ListBox* listBox;
124 StringArray baseClasses;
125 StringArray returnValues;
126 StringArray methods;
127 StringArray initialContents;
131 //==============================================================================
132 class ClassPropertiesPanel : public Component,
133 private ChangeListener
135 public:
136 ClassPropertiesPanel (JucerDocument& document_)
137 : document (document_)
139 addAndMakeVisible (panel1 = new PropertyPanel());
140 addAndMakeVisible (panel2 = new PropertyPanel());
142 Array <PropertyComponent*> props;
143 props.add (new ComponentClassNameProperty (document_));
144 props.add (new ComponentCompNameProperty (document_));
145 props.add (new ComponentParentClassesProperty (document_));
146 props.add (new ComponentConstructorParamsProperty (document_));
147 props.add (new ComponentInitialisersProperty (document_));
148 props.add (new ComponentInitialSizeProperty (document_, true));
149 props.add (new ComponentInitialSizeProperty (document_, false));
150 props.add (new FixedSizeProperty (document_));
152 panel1->addSection ("General class settings", props);
154 Array <PropertyComponent*> props2;
155 props2.add (new ExtraMethodsList (document_));
156 panel2->addSection ("Extra callback methods to generate", props2);
158 document_.addExtraClassProperties (panel1);
160 document_.addChangeListener (this);
163 ~ClassPropertiesPanel()
165 document.removeChangeListener (this);
166 deleteAllChildren();
169 void resized()
171 int pw = jmin (getWidth() / 2 - 20, 350);
172 panel1->setBounds (10, 6, pw, getHeight() - 12);
173 panel2->setBounds (panel1->getRight() + 20, panel1->getY(), pw, panel1->getHeight());
176 void changeListenerCallback (ChangeBroadcaster*)
178 panel1->refreshAll();
179 panel2->refreshAll();
182 private:
183 JucerDocument& document;
185 PropertyPanel* panel1;
186 PropertyPanel* panel2;
188 //==============================================================================
189 class ComponentClassNameProperty : public ComponentTextProperty <Component>
191 public:
192 ComponentClassNameProperty (JucerDocument& document_)
193 : ComponentTextProperty <Component> ("class name", 128, false, 0, document_)
196 void setText (const String& newText) { document.setClassName (newText); }
197 const String getText() const { return document.getClassName(); }
200 //==============================================================================
201 class ComponentCompNameProperty : public ComponentTextProperty <Component>
203 public:
204 ComponentCompNameProperty (JucerDocument& document_)
205 : ComponentTextProperty <Component> ("component name", 200, false, 0, document_)
208 void setText (const String& newText) { document.setComponentName (newText); }
209 const String getText() const { return document.getComponentName(); }
212 //==============================================================================
213 class ComponentParentClassesProperty : public ComponentTextProperty <Component>
215 public:
216 ComponentParentClassesProperty (JucerDocument& document_)
217 : ComponentTextProperty <Component> ("parent classes", 512, false, 0, document_)
220 void setText (const String& newText) { document.setParentClasses (newText); }
221 const String getText() const { return document.getParentClassString(); }
224 //==============================================================================
225 class ComponentConstructorParamsProperty : public ComponentTextProperty <Component>
227 public:
228 ComponentConstructorParamsProperty (JucerDocument& document_)
229 : ComponentTextProperty <Component> ("constructor params", 2048, false, 0, document_)
232 void setText (const String& newText) { document.setConstructorParams (newText); }
233 const String getText() const { return document.getConstructorParams(); }
236 //==============================================================================
237 class ComponentInitialisersProperty : public ComponentTextProperty <Component>
239 public:
240 ComponentInitialisersProperty (JucerDocument& document_)
241 : ComponentTextProperty <Component> ("member intialisers", 2048, true, 0, document_)
243 preferredHeight = 24 * 3;
246 void setText (const String& newText) { document.setVariableInitialisers (newText); }
247 const String getText() const { return document.getVariableInitialisers(); }
251 //==============================================================================
252 class ComponentInitialSizeProperty : public ComponentTextProperty <Component>
254 public:
255 ComponentInitialSizeProperty (JucerDocument& document_, const bool isWidth_)
256 : ComponentTextProperty <Component> (isWidth_ ? "initial width" : "initial height",
257 10, false, 0, document_),
258 isWidth (isWidth_)
261 void setText (const String& newText)
263 if (isWidth)
264 document.setInitialSize (newText.getIntValue(), document.getInitialHeight());
265 else
266 document.setInitialSize (document.getInitialWidth(), newText.getIntValue());
269 const String getText() const
271 return String (isWidth ? document.getInitialWidth()
272 : document.getInitialHeight());
275 private:
276 const bool isWidth;
279 //==============================================================================
280 class FixedSizeProperty : public ComponentChoiceProperty <Component>
282 public:
283 FixedSizeProperty (JucerDocument& document_)
284 : ComponentChoiceProperty <Component> ("fixed size", 0, document_)
286 choices.add ("Resize component to fit workspace");
287 choices.add ("Keep component size fixed");
290 void setIndex (int newIndex) { document.setFixedSize (newIndex != 0); }
291 int getIndex() const { return document.isFixedSize() ? 1 : 0; }
295 //==============================================================================
296 class CodeViewerComp : public Component,
297 private ButtonListener
299 public:
300 //==============================================================================
301 CodeViewerComp (JucerDocument& document_)
302 : document (document_),
303 isHeader (showHeaderFileFirst)
305 addAndMakeVisible (editor = new CodeEditorComponent (codeDocument, &tokeniser));
307 addAndMakeVisible (switchButton = new TextButton (String::empty));
308 switchButton->addListener (this);
310 setWantsKeyboardFocus (true);
313 ~CodeViewerComp()
315 showHeaderFileFirst = isHeader;
316 deleteAllChildren();
319 void showFile (const bool isHeader_)
321 isHeader = isHeader_;
322 editor->loadContent (isHeader ? h : cpp);
323 switchButton->setButtonText (isHeader ? "Show .cpp" : "Show .h");
326 void resized()
328 editor->setBounds (4, 4, getWidth() - 8, getHeight() - 8);
329 switchButton->setBounds (getWidth() - 130, 10, 90, 22);
332 void buttonClicked (Button*)
334 showFile (! isHeader);
337 void visibilityChanged()
339 if (isVisible())
341 document.getPreviewFiles (h, cpp);
342 showFile (isHeader);
346 //==============================================================================
347 private:
348 JucerDocument& document;
349 String h, cpp;
350 bool isHeader;
351 CodeDocument codeDocument;
352 CPlusPlusCodeTokeniser tokeniser;
353 CodeEditorComponent* editor;
354 TextButton* switchButton;
356 static bool showHeaderFileFirst;
359 bool CodeViewerComp::showHeaderFileFirst = false;
361 static const Colour tabColour (Colour (0xffc4cdcd));
364 //==============================================================================
365 JucerDocumentHolder::JucerDocumentHolder (JucerDocument* const document_)
366 : document (document_),
367 tabbedComponent (0),
368 compLayoutPanel (0),
369 lastViewportX (0),
370 lastViewportY (0),
371 currentZoomLevel (1.0)
373 jassert (document != 0);
375 setOpaque (true);
377 setSize (document->getInitialWidth(),
378 document->getInitialHeight());
380 addAndMakeVisible (tabbedComponent = new TabbedComponent (TabbedButtonBar::TabsAtRight));
381 tabbedComponent->setOutline (0);
383 tabbedComponent->addTab ("Class", tabColour, new ClassPropertiesPanel (*document), true);
385 if (document->getComponentLayout() != 0)
387 tabbedComponent->addTab ("Subcomponents", tabColour,
388 compLayoutPanel = new ComponentLayoutPanel (*document, *document->getComponentLayout()), true);
391 tabbedComponent->addTab ("Resources", tabColour, new ResourceEditorPanel (*document), true);
392 tabbedComponent->addTab ("Code Preview", tabColour, new CodeViewerComp (*document), true);
394 updateTabs();
396 tabbedComponent->setCurrentTabIndex (0);
398 document->addChangeListener (this);
400 resized();
401 refreshPropertiesPanel();
403 changeListenerCallback (0);
406 JucerDocumentHolder::~JucerDocumentHolder()
408 tabbedComponent->clearTabs();
409 deleteAndZero (tabbedComponent);
410 delete document;
413 bool JucerDocumentHolder::close()
415 MainWindow* const mw = findParentComponentOfClass ((MainWindow*) 0);
417 if (mw != 0)
418 return mw->closeDocument (this);
420 jassertfalse
421 return false;
424 void JucerDocumentHolder::refreshPropertiesPanel() const
426 if (tabbedComponent != 0)
428 for (int i = tabbedComponent->getNumTabs(); --i >= 0;)
430 ComponentLayoutPanel* layoutPanel = dynamic_cast <ComponentLayoutPanel*> (tabbedComponent->getTabContentComponent (i));
432 if (layoutPanel != 0)
434 if (layoutPanel->isVisible())
435 layoutPanel->updatePropertiesList();
437 else
439 PaintRoutinePanel* pr = dynamic_cast <PaintRoutinePanel*> (tabbedComponent->getTabContentComponent (i));
441 if (pr != 0 && pr->isVisible())
442 pr->updatePropertiesList();
448 void JucerDocumentHolder::updateTabs()
450 const StringArray paintRoutineNames (document->getPaintRoutineNames());
451 int i;
453 for (i = tabbedComponent->getNumTabs(); --i >= 0;)
455 if (dynamic_cast <PaintRoutinePanel*> (tabbedComponent->getTabContentComponent (i)) != 0
456 && ! paintRoutineNames.contains (tabbedComponent->getTabNames() [i]))
458 tabbedComponent->removeTab (i);
462 for (i = 0; i < document->getNumPaintRoutines(); ++i)
464 if (! tabbedComponent->getTabNames().contains (paintRoutineNames [i]))
466 int index, numPaintRoutinesSeen = 0;
467 for (index = 1; index < tabbedComponent->getNumTabs(); ++index)
469 if (dynamic_cast <PaintRoutinePanel*> (tabbedComponent->getTabContentComponent (index)) != 0)
471 if (++numPaintRoutinesSeen == i)
473 ++index;
474 break;
479 if (numPaintRoutinesSeen == 0)
480 index = document->getComponentLayout() != 0 ? 2 : 1;
482 tabbedComponent->addTab (paintRoutineNames[i], tabColour,
483 new PaintRoutinePanel (*document,
484 *document->getPaintRoutine (i),
485 this), true, index);
490 //==============================================================================
491 void JucerDocumentHolder::paint (Graphics& g)
493 g.fillAll (Colours::lightgrey);
495 if (tabbedComponent == 0)
497 g.setColour (Colours::black);
498 g.drawText ("no component currently open", 0, 0, getWidth(), getHeight(), Justification::centred, false);
502 void JucerDocumentHolder::resized()
504 if (tabbedComponent != 0)
505 tabbedComponent->setBounds (0, 0, getWidth(), getHeight());
508 void JucerDocumentHolder::changeListenerCallback (ChangeBroadcaster*)
510 setName (document->getClassName());
511 updateTabs();
514 //==============================================================================
515 ApplicationCommandTarget* JucerDocumentHolder::getNextCommandTarget()
517 return findFirstTargetParentComponent();
520 ComponentLayout* JucerDocumentHolder::getCurrentLayout() const
522 if (tabbedComponent != 0)
524 ComponentLayoutPanel* panel = dynamic_cast <ComponentLayoutPanel*> (tabbedComponent->getCurrentContentComponent());
526 if (panel != 0)
527 return &(panel->getLayout());
530 return 0;
533 PaintRoutine* JucerDocumentHolder::getCurrentPaintRoutine() const
535 if (tabbedComponent != 0)
537 PaintRoutinePanel* panel = dynamic_cast <PaintRoutinePanel*> (tabbedComponent->getCurrentContentComponent());
539 if (panel != 0)
540 return &(panel->getPaintRoutine());
543 return 0;
546 void JucerDocumentHolder::showLayout()
548 if (getCurrentLayout() == 0 && tabbedComponent != 0)
550 for (int i = 0; i < tabbedComponent->getNumTabs(); ++i)
552 if (dynamic_cast <ComponentLayoutPanel*> (tabbedComponent->getTabContentComponent (i)) != 0)
554 tabbedComponent->setCurrentTabIndex (i);
555 break;
561 void JucerDocumentHolder::showGraphics (PaintRoutine* routine)
563 if ((getCurrentPaintRoutine() != routine || routine == 0) && tabbedComponent != 0)
565 for (int i = 0; i < tabbedComponent->getNumTabs(); ++i)
567 PaintRoutinePanel* pr = dynamic_cast <PaintRoutinePanel*> (tabbedComponent->getTabContentComponent (i));
569 if (pr != 0 && (routine == &(pr->getPaintRoutine()) || routine == 0))
571 tabbedComponent->setCurrentTabIndex (i);
572 break;
578 //==============================================================================
579 void JucerDocumentHolder::setViewportToLastPos (Viewport* vp, EditingPanelBase& editor)
581 vp->setViewPosition (lastViewportX, lastViewportY);
582 editor.setZoom (currentZoomLevel);
585 void JucerDocumentHolder::storeLastViewportPos (Viewport* vp, EditingPanelBase& editor)
587 lastViewportX = vp->getViewPositionX();
588 lastViewportY = vp->getViewPositionY();
590 currentZoomLevel = editor.getZoom();
593 void JucerDocumentHolder::setZoom (double scale)
595 scale = jlimit (1.0 / 4.0, 32.0, scale);
597 if (tabbedComponent != 0)
599 EditingPanelBase* panel = dynamic_cast <EditingPanelBase*> (tabbedComponent->getCurrentContentComponent());
601 if (panel != 0)
602 panel->setZoom (scale);
606 double JucerDocumentHolder::getZoom() const
608 if (tabbedComponent != 0)
610 EditingPanelBase* panel = dynamic_cast <EditingPanelBase*> (tabbedComponent->getCurrentContentComponent());
612 if (panel != 0)
613 return panel->getZoom();
616 return 1.0;
619 void JucerDocumentHolder::addElement (const int index)
621 if (tabbedComponent != 0)
623 PaintRoutinePanel* const panel = dynamic_cast <PaintRoutinePanel*> (tabbedComponent->getCurrentContentComponent());
625 if (panel != 0)
627 PaintRoutine* const currentPaintRoutine = & (panel->getPaintRoutine());
628 const Rectangle<int> area (panel->getComponentArea());
630 document->getUndoManager().beginNewTransaction();
632 PaintElement* e = ObjectTypes::createNewElement (index, currentPaintRoutine);
634 e->setInitialBounds (area.getWidth(), area.getHeight());
636 e = currentPaintRoutine->addNewElement (e, -1, true);
638 if (e != 0)
640 const int randomness = jmin (80, area.getWidth() / 2, area.getHeight() / 2);
641 int x = area.getX() + area.getWidth() / 2 + Random::getSystemRandom().nextInt (randomness) - randomness / 2;
642 int y = area.getY() + area.getHeight() / 2 + Random::getSystemRandom().nextInt (randomness) - randomness / 2;
643 x = document->snapPosition (x);
644 y = document->snapPosition (y);
646 panel->xyToTargetXY (x, y);
648 Rectangle<int> r (e->getCurrentBounds (area));
649 r.setPosition (x, y);
650 e->setCurrentBounds (r, area, true);
652 currentPaintRoutine->getSelectedElements().selectOnly (e);
655 document->getUndoManager().beginNewTransaction();
660 void JucerDocumentHolder::addComponent (const int index)
662 if (tabbedComponent != 0)
664 showLayout();
665 ComponentLayoutPanel* const panel = dynamic_cast <ComponentLayoutPanel*> (tabbedComponent->getCurrentContentComponent());
667 if (panel != 0)
669 const Rectangle<int> area (panel->getComponentArea());
671 document->getUndoManager().beginNewTransaction ("Add new " + ObjectTypes::componentTypeHandlers [index]->getTypeName());
673 const int randomness = jmin (80, area.getWidth() / 2, area.getHeight() / 2);
674 int x = area.getWidth() / 2 + Random::getSystemRandom().nextInt (randomness) - randomness / 2;
675 int y = area.getHeight() / 2 + Random::getSystemRandom().nextInt (randomness) - randomness / 2;
676 x = document->snapPosition (x);
677 y = document->snapPosition (y);
679 panel->xyToTargetXY (x, y);
681 Component* newOne = panel->getLayout().addNewComponent (ObjectTypes::componentTypeHandlers [index], x, y);
683 if (newOne != 0)
684 panel->getLayout().getSelectedSet().selectOnly (newOne);
686 document->getUndoManager().beginNewTransaction();
691 //==============================================================================
692 bool JucerDocumentHolder::isSomethingSelected() const
694 ComponentLayout* layout = getCurrentLayout();
696 if (layout != 0)
697 return layout->getSelectedSet().getNumSelected() > 0;
699 PaintRoutine* routine = getCurrentPaintRoutine();
701 if (routine != 0)
702 return routine->getSelectedElements().getNumSelected() > 0;
704 return false;
707 //==============================================================================
708 void JucerDocumentHolder::getAllCommands (Array <CommandID>& commands)
710 const CommandID ids[] =
712 CommandIDs::close,
713 CommandIDs::save,
714 CommandIDs::saveAs,
715 CommandIDs::undo,
716 CommandIDs::redo,
717 CommandIDs::test,
718 CommandIDs::toFront,
719 CommandIDs::toBack,
720 CommandIDs::group,
721 CommandIDs::ungroup,
722 CommandIDs::bringBackLostItems,
723 CommandIDs::enableSnapToGrid,
724 CommandIDs::showGrid,
725 CommandIDs::editCompLayout,
726 CommandIDs::editCompGraphics,
727 CommandIDs::zoomIn,
728 CommandIDs::zoomOut,
729 CommandIDs::zoomNormal,
730 CommandIDs::spaceBarDrag,
731 CommandIDs::compOverlay0,
732 CommandIDs::compOverlay33,
733 CommandIDs::compOverlay66,
734 CommandIDs::compOverlay100,
735 StandardApplicationCommandIDs::cut,
736 StandardApplicationCommandIDs::copy,
737 StandardApplicationCommandIDs::paste,
738 StandardApplicationCommandIDs::del,
739 StandardApplicationCommandIDs::selectAll,
740 StandardApplicationCommandIDs::deselectAll
743 commands.addArray (ids, numElementsInArray (ids));
745 int i;
746 for (i = 0; i < ObjectTypes::numComponentTypes; ++i)
747 commands.add (CommandIDs::newComponentBase + i);
749 for (i = 0; i < ObjectTypes::numElementTypes; ++i)
750 commands.add (CommandIDs::newElementBase + i);
753 void JucerDocumentHolder::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
755 ComponentLayout* const currentLayout = getCurrentLayout();
756 PaintRoutine* const currentPaintRoutine = getCurrentPaintRoutine();
758 const int cmd = ModifierKeys::commandModifier;
759 const int shift = ModifierKeys::shiftModifier;
761 if (commandID >= CommandIDs::newComponentBase
762 && commandID < CommandIDs::newComponentBase + ObjectTypes::numComponentTypes)
764 const int index = commandID - CommandIDs::newComponentBase;
766 result.setInfo ("New " + ObjectTypes::componentTypeHandlers [index]->getTypeName(),
767 "Creates a new " + ObjectTypes::componentTypeHandlers [index]->getTypeName(),
768 CommandCategories::editing, 0);
769 return;
772 if (commandID >= CommandIDs::newElementBase
773 && commandID < CommandIDs::newElementBase + ObjectTypes::numElementTypes)
775 const int index = commandID - CommandIDs::newElementBase;
777 result.setInfo (String ("New ") + ObjectTypes::elementTypeNames [index],
778 String ("Adds a new ") + ObjectTypes::elementTypeNames [index],
779 CommandCategories::editing, 0);
781 result.setActive (currentPaintRoutine != 0);
782 return;
785 switch (commandID)
787 case CommandIDs::close:
788 result.setInfo ("Close",
789 "Closes the component that's currently being edited.",
790 CommandCategories::general, 0);
791 break;
793 case CommandIDs::save:
794 result.setInfo ("Save",
795 "Saves the current component.",
796 CommandCategories::general, 0);
798 result.defaultKeypresses.add (KeyPress ('s', cmd, 0));
799 break;
802 case CommandIDs::saveAs:
803 result.setInfo ("Save As...",
804 "Saves the current component to a specified file.",
805 CommandCategories::general, 0);
806 result.defaultKeypresses.add (KeyPress ('s', cmd | shift, 0));
807 break;
809 case CommandIDs::undo:
810 result.setInfo ("Undo",
811 "Undoes the last operation.",
812 CommandCategories::editing, 0);
813 result.setActive (document->getUndoManager().canUndo());
814 result.defaultKeypresses.add (KeyPress ('z', cmd, 0));
815 break;
817 case CommandIDs::redo:
818 result.setInfo ("Redo",
819 "Redoes the last operation.",
820 CommandCategories::editing, 0);
821 result.setActive (document->getUndoManager().canRedo());
822 result.defaultKeypresses.add (KeyPress ('z', cmd | shift, 0));
823 result.defaultKeypresses.add (KeyPress ('y', cmd, 0));
824 break;
826 case CommandIDs::toFront:
827 result.setInfo ("Bring to front",
828 "Brings the currently selected component to the front.",
829 CommandCategories::editing, 0);
830 result.setActive (isSomethingSelected());
831 result.defaultKeypresses.add (KeyPress ('f', cmd, 0));
832 break;
834 case CommandIDs::toBack:
835 result.setInfo ("Send to back",
836 "Sends the currently selected component to the back.",
837 CommandCategories::editing, 0);
838 result.setActive (isSomethingSelected());
839 result.defaultKeypresses.add (KeyPress ('b', cmd, 0));
840 break;
842 case CommandIDs::group:
843 result.setInfo ("Group selected items",
844 "Turns the currently selected elements into a single group object.",
845 CommandCategories::editing, 0);
846 result.setActive (currentPaintRoutine != 0
847 && currentPaintRoutine->getSelectedElements().getNumSelected() > 1);
848 result.defaultKeypresses.add (KeyPress ('k', cmd, 0));
849 break;
851 case CommandIDs::ungroup:
852 result.setInfo ("Ungroup selected items",
853 "Turns the currently selected elements into a single group object.",
854 CommandCategories::editing, 0);
855 result.setActive (currentPaintRoutine != 0
856 && currentPaintRoutine->getSelectedElements().getNumSelected() == 1
857 && currentPaintRoutine->getSelectedElements().getSelectedItem (0)->getTypeName() == "Group");
858 result.defaultKeypresses.add (KeyPress ('k', cmd | shift, 0));
859 break;
861 case CommandIDs::test:
862 result.setInfo ("Test component...",
863 "Runs the current component interactively.",
864 CommandCategories::view, 0);
865 result.defaultKeypresses.add (KeyPress ('t', cmd, 0));
866 break;
868 case CommandIDs::enableSnapToGrid:
869 result.setInfo ("Enable snap-to-grid",
870 "Toggles whether components' positions are aligned to a grid.",
871 CommandCategories::view, 0);
872 result.setTicked (document->isSnapActive (false));
873 result.defaultKeypresses.add (KeyPress ('g', cmd, 0));
874 break;
876 case CommandIDs::showGrid:
877 result.setInfo ("Show snap-to-grid",
878 "Toggles whether the snapping grid is displayed on-screen.",
879 CommandCategories::view, 0);
880 result.setTicked (document->isSnapShown());
881 result.defaultKeypresses.add (KeyPress ('g', cmd | shift, 0));
882 break;
884 case CommandIDs::editCompLayout:
885 result.setInfo ("Edit sub-component layout",
886 "Switches to the sub-component editor view.",
887 CommandCategories::view, 0);
888 result.setActive (tabbedComponent != 0);
889 result.setTicked (currentLayout != 0);
890 result.defaultKeypresses.add (KeyPress ('n', cmd, 0));
891 break;
893 case CommandIDs::editCompGraphics:
894 result.setInfo ("Edit background graphics",
895 "Switches to the background graphics editor view.",
896 CommandCategories::view, 0);
897 result.setActive (tabbedComponent != 0);
898 result.setTicked (currentPaintRoutine != 0);
899 result.defaultKeypresses.add (KeyPress ('m', cmd, 0));
900 break;
902 case CommandIDs::bringBackLostItems:
903 result.setInfo ("Retrieve offscreen items",
904 "Moves any items that are lost beyond the edges of the screen back to the centre.",
905 CommandCategories::editing, 0);
906 result.setActive (currentPaintRoutine != 0 || currentLayout != 0);
907 result.defaultKeypresses.add (KeyPress ('m', cmd, 0));
908 break;
910 case CommandIDs::zoomIn:
911 result.setInfo ("Zoom in",
912 "Zooms in on the current component.",
913 CommandCategories::editing, 0);
914 result.setActive (currentPaintRoutine != 0 || currentLayout != 0);
915 result.defaultKeypresses.add (KeyPress (']', cmd, 0));
916 break;
918 case CommandIDs::zoomOut:
919 result.setInfo ("Zoom out",
920 "Zooms out on the current component.",
921 CommandCategories::editing, 0);
922 result.setActive (currentPaintRoutine != 0 || currentLayout != 0);
923 result.defaultKeypresses.add (KeyPress ('[', cmd, 0));
924 break;
926 case CommandIDs::zoomNormal:
927 result.setInfo ("Zoom to 100%",
928 "Restores the zoom level to normal.",
929 CommandCategories::editing, 0);
930 result.setActive (currentPaintRoutine != 0 || currentLayout != 0);
931 result.defaultKeypresses.add (KeyPress ('1', cmd, 0));
932 break;
934 case CommandIDs::spaceBarDrag:
935 result.setInfo ("Scroll while dragging mouse",
936 "When held down, this key lets you scroll around by dragging with the mouse.",
937 CommandCategories::view, ApplicationCommandInfo::wantsKeyUpDownCallbacks);
938 result.setActive (currentPaintRoutine != 0 || currentLayout != 0);
939 result.defaultKeypresses.add (KeyPress (KeyPress::spaceKey, 0, 0));
940 break;
942 case CommandIDs::compOverlay0:
943 case CommandIDs::compOverlay33:
944 case CommandIDs::compOverlay66:
945 case CommandIDs::compOverlay100:
947 int amount = 0, num = 0;
949 if (commandID == CommandIDs::compOverlay33)
951 amount = 33;
952 num = 1;
954 else if (commandID == CommandIDs::compOverlay66)
956 amount = 66;
957 num = 2;
959 else if (commandID == CommandIDs::compOverlay100)
961 amount = 100;
962 num = 3;
965 result.defaultKeypresses.add (KeyPress ('2' + num, cmd, 0));
967 int currentAmount = 0;
968 if (document->getComponentOverlayOpacity() > 0.9f)
969 currentAmount = 100;
970 else if (document->getComponentOverlayOpacity() > 0.6f)
971 currentAmount = 66;
972 else if (document->getComponentOverlayOpacity() > 0.3f)
973 currentAmount = 33;
975 result.setInfo (commandID == CommandIDs::compOverlay0
976 ? "No component overlay"
977 : "Overlay with opacity of " + String (amount) + "%",
978 "Changes the opacity of the components that are shown over the top of the graphics editor.",
979 CommandCategories::view, 0);
980 result.setActive (currentPaintRoutine != 0 && document->getComponentLayout() != 0);
981 result.setTicked (amount == currentAmount);
983 break;
985 case StandardApplicationCommandIDs::cut:
986 result.setInfo ("Cut",
987 "Copies the currently selected components to the clipboard and deletes them.",
988 CommandCategories::editing, 0);
989 result.setActive (isSomethingSelected());
990 result.defaultKeypresses.add (KeyPress ('x', cmd, 0));
991 break;
993 case StandardApplicationCommandIDs::copy:
994 result.setInfo ("Copy",
995 "Copies the currently selected components to the clipboard.",
996 CommandCategories::editing, 0);
997 result.setActive (isSomethingSelected());
998 result.defaultKeypresses.add (KeyPress ('c', cmd, 0));
999 break;
1001 case StandardApplicationCommandIDs::paste:
1003 result.setInfo ("Paste",
1004 "Pastes any components from the clipboard.",
1005 CommandCategories::editing, 0);
1006 result.defaultKeypresses.add (KeyPress ('v', cmd, 0));
1008 bool canPaste = false;
1009 XmlDocument clip (SystemClipboard::getTextFromClipboard());
1010 XmlElement* const doc = clip.getDocumentElement (true);
1012 if (doc != 0)
1014 if (doc->hasTagName (ComponentLayout::clipboardXmlTag))
1015 canPaste = (currentLayout != 0);
1016 else if (doc->hasTagName (PaintRoutine::clipboardXmlTag))
1017 canPaste = (currentPaintRoutine != 0);
1019 delete doc;
1022 result.setActive (canPaste);
1025 break;
1027 case StandardApplicationCommandIDs::del:
1028 result.setInfo ("Delete",
1029 "Deletes any selected components.",
1030 CommandCategories::editing, 0);
1031 result.setActive (isSomethingSelected());
1032 result.defaultKeypresses.add (KeyPress (KeyPress::deleteKey, 0, 0));
1033 result.defaultKeypresses.add (KeyPress (KeyPress::backspaceKey, 0, 0));
1034 break;
1036 case StandardApplicationCommandIDs::selectAll:
1037 result.setInfo ("Select All",
1038 "Selects all of whatever item is currently selected.",
1039 CommandCategories::editing, 0);
1040 result.setActive (currentPaintRoutine != 0 || currentLayout != 0);
1041 result.defaultKeypresses.add (KeyPress ('a', cmd, 0));
1042 break;
1044 case StandardApplicationCommandIDs::deselectAll:
1045 result.setInfo ("Deselect All",
1046 "Deselects whatever is currently selected.",
1047 CommandCategories::editing, 0);
1048 result.setActive (currentPaintRoutine != 0 || currentLayout != 0);
1049 result.defaultKeypresses.add (KeyPress ('d', cmd, 0));
1050 break;
1052 default:
1053 break;
1057 bool JucerDocumentHolder::perform (const InvocationInfo& info)
1059 ComponentLayout* const currentLayout = getCurrentLayout();
1060 PaintRoutine* const currentPaintRoutine = getCurrentPaintRoutine();
1062 document->getUndoManager().beginNewTransaction();
1064 if (info.commandID >= CommandIDs::newComponentBase
1065 && info.commandID < CommandIDs::newComponentBase + ObjectTypes::numComponentTypes)
1067 addComponent (info.commandID - CommandIDs::newComponentBase);
1068 return true;
1071 if (info.commandID >= CommandIDs::newElementBase
1072 && info.commandID < CommandIDs::newElementBase + ObjectTypes::numElementTypes)
1074 addElement (info.commandID - CommandIDs::newElementBase);
1075 return true;
1078 switch (info.commandID)
1080 case CommandIDs::close:
1081 close();
1082 // (this comp will now be deleted)
1083 return true;
1085 case CommandIDs::save:
1086 document->save (true, true);
1087 break;
1089 case CommandIDs::saveAs:
1090 document->saveAsInteractive (true);
1091 break;
1093 case CommandIDs::undo:
1094 document->getUndoManager().undo();
1095 document->dispatchPendingMessages();
1096 break;
1098 case CommandIDs::redo:
1099 document->getUndoManager().redo();
1100 document->dispatchPendingMessages();
1101 break;
1103 case CommandIDs::test:
1104 TestComponent::showInDialogBox (*document);
1105 break;
1107 case CommandIDs::enableSnapToGrid:
1108 document->setSnappingGrid (document->getSnappingGridSize(),
1109 ! document->isSnapActive (false),
1110 document->isSnapShown());
1111 break;
1113 case CommandIDs::showGrid:
1114 document->setSnappingGrid (document->getSnappingGridSize(),
1115 document->isSnapActive (false),
1116 ! document->isSnapShown());
1117 break;
1119 case CommandIDs::editCompLayout:
1120 showLayout();
1121 break;
1123 case CommandIDs::editCompGraphics:
1124 showGraphics (0);
1125 break;
1127 case CommandIDs::zoomIn:
1128 setZoom (getZoom() * 2.0);
1129 break;
1131 case CommandIDs::zoomOut:
1132 setZoom (getZoom() / 2.0);
1133 break;
1135 case CommandIDs::zoomNormal:
1136 setZoom (1.0);
1137 break;
1139 case CommandIDs::spaceBarDrag:
1141 EditingPanelBase* panel = dynamic_cast <EditingPanelBase*> (tabbedComponent->getCurrentContentComponent());
1143 if (panel != 0)
1144 panel->dragKeyHeldDown (info.isKeyDown);
1146 break;
1149 case CommandIDs::compOverlay0:
1150 case CommandIDs::compOverlay33:
1151 case CommandIDs::compOverlay66:
1152 case CommandIDs::compOverlay100:
1154 int amount = 0;
1156 if (info.commandID == CommandIDs::compOverlay33)
1157 amount = 33;
1158 else if (info.commandID == CommandIDs::compOverlay66)
1159 amount = 66;
1160 else if (info.commandID == CommandIDs::compOverlay100)
1161 amount = 100;
1163 document->setComponentOverlayOpacity (amount * 0.01f);
1165 break;
1167 case CommandIDs::bringBackLostItems:
1169 EditingPanelBase* panel = dynamic_cast <EditingPanelBase*> (tabbedComponent->getCurrentContentComponent());
1171 if (panel != 0)
1173 int w = panel->getComponentArea().getWidth();
1174 int h = panel->getComponentArea().getHeight();
1176 if (currentPaintRoutine != 0)
1177 currentPaintRoutine->bringLostItemsBackOnScreen (panel->getComponentArea());
1178 else if (currentLayout != 0)
1179 currentLayout->bringLostItemsBackOnScreen (w, h);
1182 break;
1185 case CommandIDs::toFront:
1186 if (currentLayout != 0)
1187 currentLayout->selectedToFront();
1188 else if (currentPaintRoutine != 0)
1189 currentPaintRoutine->selectedToFront();
1191 break;
1193 case CommandIDs::toBack:
1194 if (currentLayout != 0)
1195 currentLayout->selectedToBack();
1196 else if (currentPaintRoutine != 0)
1197 currentPaintRoutine->selectedToBack();
1199 break;
1201 case CommandIDs::group:
1202 if (currentPaintRoutine != 0)
1203 currentPaintRoutine->groupSelected();
1204 break;
1206 case CommandIDs::ungroup:
1207 if (currentPaintRoutine != 0)
1208 currentPaintRoutine->ungroupSelected();
1209 break;
1211 case StandardApplicationCommandIDs::cut:
1212 if (currentLayout != 0)
1214 currentLayout->copySelectedToClipboard();
1215 currentLayout->deleteSelected();
1217 else if (currentPaintRoutine != 0)
1219 currentPaintRoutine->copySelectedToClipboard();
1220 currentPaintRoutine->deleteSelected();
1223 break;
1225 case StandardApplicationCommandIDs::copy:
1226 if (currentLayout != 0)
1227 currentLayout->copySelectedToClipboard();
1228 else if (currentPaintRoutine != 0)
1229 currentPaintRoutine->copySelectedToClipboard();
1231 break;
1233 case StandardApplicationCommandIDs::paste:
1235 XmlDocument clip (SystemClipboard::getTextFromClipboard());
1236 XmlElement* const doc = clip.getDocumentElement (true);
1238 if (doc != 0)
1240 if (doc->hasTagName (ComponentLayout::clipboardXmlTag))
1242 if (currentLayout != 0)
1243 currentLayout->paste();
1245 else if (doc->hasTagName (PaintRoutine::clipboardXmlTag))
1247 if (currentPaintRoutine != 0)
1248 currentPaintRoutine->paste();
1251 delete doc;
1254 break;
1256 case StandardApplicationCommandIDs::del:
1257 if (currentLayout != 0)
1258 currentLayout->deleteSelected();
1259 else if (currentPaintRoutine != 0)
1260 currentPaintRoutine->deleteSelected();
1262 break;
1264 case StandardApplicationCommandIDs::selectAll:
1265 if (currentLayout != 0)
1266 currentLayout->selectAll();
1267 else if (currentPaintRoutine != 0)
1268 currentPaintRoutine->selectAll();
1269 break;
1271 case StandardApplicationCommandIDs::deselectAll:
1272 if (currentLayout != 0)
1274 currentLayout->getSelectedSet().deselectAll();
1276 else if (currentPaintRoutine != 0)
1278 currentPaintRoutine->getSelectedElements().deselectAll();
1279 currentPaintRoutine->getSelectedPoints().deselectAll();
1282 break;
1284 default:
1285 return false;
1288 document->getUndoManager().beginNewTransaction();
1289 return true;
1292 JucerDocumentHolder* JucerDocumentHolder::getActiveDocumentHolder()
1294 ApplicationCommandInfo info (0);
1295 ApplicationCommandTarget* target = commandManager->getTargetForCommand (CommandIDs::close, info);
1297 return dynamic_cast <JucerDocumentHolder*> (target);
1300 const Image JucerDocumentHolder::createComponentLayerSnapshot() const
1302 if (compLayoutPanel != 0)
1303 return compLayoutPanel->createComponentSnapshot();
1305 return Image();